/*&h{*/
#ifndef FILE
#include <stdio.h>
#endif
/*&h}*/

#include <ctype.h>
#include <string.h>

/*&h{*/
typedef struct
	{
	int line, col, cur;
	unsigned int spaces:1, skipcomments:1;
	FILE *fp;
	} tTextFile;

typedef struct
	{
	int line, col, cur;
	long fpos;
	} tTextFilePos;

#define TF_SPACES 0x01 /* \n und \t durch spaces ersetzen */
#define TF_SKIPCOMMENTS 0x02
/*&h}*/


/*&hf*/
int TextOpenFile(tTextFile *tf, char *Name, int Flags)
	{
	if (Name == NULL)
		tf->fp = stdin;
	else
		if ((tf->fp = fopen(Name, "r")) == NULL)
			return (-1);
	tf->line = 1;
	tf->col = 1;
	tf->spaces = (Flags & TF_SPACES) != 0;
	tf->skipcomments = (Flags & TF_SKIPCOMMENTS) != 0;
	tf->cur = getc(tf->fp);
	return (0);
	} /* TextOpenFile() */


/*&hf*/
int TextCloseFile(tTextFile *tf)
	{
	return (fclose(tf->fp));
	}


/*&hf*/
int TextFileGetPos(tTextFile *tf, tTextFilePos *tp)
	{
	tp->fpos = ftell(tf->fp);
	if (tp->fpos < 0)
		return (-1);
	tp->cur = tf->cur;
	tp->line = tf->line;
	tp->col = tf->col;
	return (0);
	}


/*&hf*/
int TextFileSetPos(tTextFile *tf, tTextFilePos *tp)
	{
	if (fseek(tf->fp, tp->fpos, SEEK_SET) != 0)
		return (-1);
	tf->cur = tp->cur;
	tf->line = tp->line;
	tf->col = tp->col;
	return (0);
	}


/*&hf*/
int TextCurC(tTextFile *tf)
	{
	if ((tf)->skipcomments && (tf)->cur == ';')
		return ((tf)->spaces ? ' ' : '\n');
	else if ((tf)->spaces && isspace((tf)->cur))
		return (' ');
	else
		return ((tf)->cur);
	}


/*&hf*/
int TextNextC(tTextFile *tf)
	{
	int c;

	switch (tf->cur)
		{
		case EOF :
			return (EOF);
		case ';' :
			if (!tf->skipcomments)
				{
				tf->col++;
				break;
				}
			do
				c = getc(tf->fp);
				while (c != EOF && c != '\n');
			if (c == EOF)
				return (tf->cur = EOF); /* Zuweisung! */
			/* weiter mit \n */
		case '\n' :
			tf->line++;
			tf->col = 1;
			break;
		case '\t' :
			tf->col = ((tf->col + 7) / 8) * 8 + 1;
			break;
		default :
			tf->col++;
			break;
		}
	tf->cur = getc(tf->fp);
	return (TextCurC(tf));
	} /* TextNextC() */


/*&hf*/
int TextNextNonSpace(tTextFile *tf)
	{
	while (isspace(TextCurC(tf)))
		TextNextC(tf);
	return (TextCurC(tf));
	}


/*&hf*/
int TextGetC(tTextFile *tf)
	{
	int c;

	c = TextCurC(tf);
	TextNextC(tf);
	return (c);
	}


/*&hf*/
int TextGetNonSpace(tTextFile *tf)
	{
	TextNextNonSpace(tf);
	return (TextGetC(tf));
	}


/*&hf*/
int TextGetName(tTextFile *tf, char *s, int len)
	{
	char *p;
	int c;

	TextNextNonSpace(tf);
	p = s;
	c = TextCurC(tf);
	while (isalnum(c))
		{
		if (p - s < len-1)
			*p++ = c;
		TextNextC(tf);
		c = TextCurC(tf);
		}
	*p = '\0';
	return ((c == EOF && p == s) ? EOF : p - s);
	}


/*&hf*/
int TextGetStringDelim(tTextFile *tf, char *s, int len, char *Delim)
	{
	char *p;
	int c;

	TextNextNonSpace(tf);
	p = s;
	if (Delim == NULL)
		Delim = "";
	c = TextCurC(tf);
	while (c != EOF
		   && c != '\n'
		   && !(tf->spaces && c == ' ')
		   && strchr(Delim, c) == NULL)
		{
		if (p - s < len-1)
			*p++ = c;
		TextNextC(tf);
		c = TextCurC(tf);
		}
	*p = '\0';
	return ((c == EOF && p == s) ? EOF : p - s);
	}


/*&hf*/
int TextGetString(tTextFile *tf, char *s, int len)
	{
	return (TextGetStringDelim(tf, s, len, NULL));
	}


/*&hf*/
int TextGetInt(tTextFile *tf, int *i)
	{
	int neg;

	TextNextNonSpace(tf);
	*i = 0;
	neg = 0;
	switch (TextCurC(tf))
		{
		case EOF :
			return (EOF);
		case '+' :
			TextNextC(tf);
			break;
		case '-' :
			neg = 1;
			TextNextC(tf);
			break;
		}
	if (!isdigit(TextCurC(tf)))
		return (0);
	while (isdigit(TextCurC(tf)))
		{
		*i = *i * 10 + TextCurC(tf) - '0';
		TextNextC(tf);
		}
	if (neg)
		*i = -*i;
	return (1);
	}


